package com.ziytek.web.citizen.listener;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.ziytek.web.citizen.constant.NumConstant;
import com.ziytek.web.citizen.constant.ServerConstant;
import com.ziytek.web.citizen.enums.StepTypeNoEnum;
import com.ziytek.web.citizen.event.StepSettingEvent;
import com.ziytek.web.citizen.mapper.SettingDetailMapper;
import com.ziytek.web.citizen.model.bean.AddSettings;
import com.ziytek.web.citizen.service.SettingService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.Comparator;
import java.util.List;

/***
 * 工步方案新增、修改及删除事件监听
 * @author fenghx
 * */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class StepSettingEventListener {

    private final Gson gson;
    private final SettingService settingService;
    private final SettingDetailMapper settingDetailMapper;


    @Async("myAsyncExecutor")
    @EventListener
    public void stepSettingEventListener(StepSettingEvent event) {
        Assert.notNull(event, "StepSettingEvent can not be null");
        Assert.notNull(event.getLoop(), "StepSettingEvent loop can not be null");
        Assert.notNull(event.getFlag(), "StepSettingEvent flag can not be null");
        Assert.notNull(event.getStepId(), "StepSettingEvent stepId can not be null");
        Assert.notNull(event.getSettingList(), "StepSettingEvent settingListString can not be null");

        List<AddSettings> settingList = gson.fromJson(event.getSettingList(), new TypeToken<List<AddSettings>>() {
        }.getType());

        Assert.notEmpty(settingList, "StepSettingEvent settingList can not be null");

        var loop = event.getLoop();
        var stepId = event.getStepId();
        var loopOrderEnd = event.getLoopOrderEnd();
        var loopOrderBegin = event.getLoopOrderBegin();
        // 排序
        settingList.sort(Comparator.comparingInt(AddSettings::getSettingOrder));

        if (event.getFlag() == ServerConstant.STEP_SETTING_TYPE_MODIFY || event.getFlag() == ServerConstant.STEP_SETTING_TYPE_DELETE) {
            settingDetailMapper.deleteByStepId(stepId, System.currentTimeMillis());
            settingDetailMapper.deleteByInterruptOrEndStepId(stepId, System.currentTimeMillis());
        }

        addOrModify(event, settingList, stepId, loop, loopOrderBegin, loopOrderEnd);
    }

    private void addOrModifyOld(StepSettingEvent event, List<AddSettings> settingList, Long stepId, Integer loop, Integer loopOrderBegin, Integer loopOrderEnd) {
        boolean addOrModify = event.getFlag() == ServerConstant.STEP_SETTING_TYPE_ADD || event.getFlag() == ServerConstant.STEP_SETTING_TYPE_MODIFY;
        if (!addOrModify) {
            return;
        }

        var order = NumConstant.INT_ZERO;
        for (var setting : settingList) {
            // 搁置指令前，增加一个停止指令
            if (StepTypeNoEnum.STEP_TYPE_SL_NUM.getCode().equalsIgnoreCase(setting.getSetType())) {
                order = order + NumConstant.INT_ONE;
                settingService.endSettingDetailSave(NumConstant.LONG_LT_TEN, order, stepId);
            }

            order = order + NumConstant.INT_ONE;
            settingService.settingDetailSave(setting, stepId, order);

            if (loop <= NumConstant.INT_ZERO) {
                continue;
            }

            // 循环次数大于0，则循环
            if (setting.getSettingOrder().equals(loopOrderBegin)) {
                // 补全第一次循环
                for (var settingLoop : settingList) {
                    if (settingLoop.getSettingOrder() > loopOrderBegin && settingLoop.getSettingOrder() <= loopOrderEnd) {
                        // 搁置指令前，增加一个停止指令
                        if (StepTypeNoEnum.STEP_TYPE_SL_NUM.getCode().equalsIgnoreCase(settingLoop.getSetType())) {
                            order = order + NumConstant.INT_ONE;
                            settingService.endSettingDetailSave(NumConstant.LONG_LT_TEN, order, stepId);
                        }

                        order = order + NumConstant.INT_ONE;
                        settingService.settingDetailSave(settingLoop, stepId, order);
                    }
                }

                // 只有一次循环
                if (loop == NumConstant.INT_ONE) {
                    // 搁置指令前，增加一个停止指令
                    if (StepTypeNoEnum.STEP_TYPE_SL_NUM.getCode().equalsIgnoreCase(setting.getSetType())) {
                        order = order + NumConstant.INT_ONE;
                        settingService.endSettingDetailSave(NumConstant.LONG_LT_TEN, order, stepId);
                    }

                    order = order + NumConstant.INT_ONE;
                    settingService.settingDetailSave(setting, stepId, order);

                    continue;
                }

                //  中间n-2次循环
                for (int i = NumConstant.INT_ONE; i < loop; i++) {
                    for (var settingLoop : settingList) {
                        if (settingLoop.getSettingOrder() >= loopOrderBegin && settingLoop.getSettingOrder() <= loopOrderEnd) {
                            // 搁置指令前，增加一个停止指令
                            if (StepTypeNoEnum.STEP_TYPE_SL_NUM.getCode().equalsIgnoreCase(settingLoop.getSetType())) {
                                order = order + NumConstant.INT_ONE;
                                settingService.endSettingDetailSave(NumConstant.LONG_LT_TEN, order, stepId);
                            }

                            order = order + NumConstant.INT_ONE;
                            settingService.settingDetailSave(settingLoop, stepId, order);
                        }
                    }
                }

                // 搁置指令前，增加一个停止指令
                if (StepTypeNoEnum.STEP_TYPE_SL_NUM.getCode().equalsIgnoreCase(setting.getSetType())) {
                    order = order + NumConstant.INT_ONE;
                    settingService.endSettingDetailSave(NumConstant.LONG_LT_TEN, order, stepId);
                }

                // 循环次数大于2，则补全最后一次循环
                order = order + NumConstant.INT_ONE;
                settingService.settingDetailSave(setting, stepId, order);
            }
        }

        // 循环结束后，最后增加一条结束指令
        order = order + NumConstant.INT_ONE;
        settingService.endSettingDetailSave(NumConstant.LONG_LT_TEN, order, stepId);
    }

    private void addOrModify(StepSettingEvent event, List<AddSettings> settingList, Long stepId, Integer loop, Integer loopOrderBegin, Integer loopOrderEnd) {
        boolean addOrModify = event.getFlag() == ServerConstant.STEP_SETTING_TYPE_ADD || event.getFlag() == ServerConstant.STEP_SETTING_TYPE_MODIFY;
        if (!addOrModify) {
            return;
        }

        // 没有工步循环
        if (loop <= NumConstant.INT_ZERO) {
            getNotLoop(settingList, stepId);
            return;
        }

        getHasLoop(settingList, stepId, loop, loopOrderBegin, loopOrderEnd);

    }

    private void getNotLoop(List<AddSettings> settingList, Long stepId) {
        var order = NumConstant.INT_ZERO;
        for (var setting : settingList) {
            order = order + NumConstant.INT_ONE;
            settingService.settingDetailSave(setting, stepId, order);

            // 不是搁置指令的后面，增加一个结束指令
            if (!StepTypeNoEnum.STEP_TYPE_SL_NUM.getCode().equalsIgnoreCase(setting.getSetType())) {
                order = order + NumConstant.INT_ONE;
                settingService.endSettingDetailSave(NumConstant.LONG_LT_TEN, order, stepId);
            }
        }
    }

    private void getHasLoop(List<AddSettings> settingList, Long stepId, Integer loop, Integer loopOrderBegin, Integer loopOrderEnd) {
        var order = NumConstant.INT_ZERO;

        for (var st : settingList) {

            order = order + NumConstant.INT_ONE;
            settingService.settingDetailSave(st, stepId, order);

            // 不是搁置指令的后面，增加一个结束指令
            if (!StepTypeNoEnum.STEP_TYPE_SL_NUM.getCode().equalsIgnoreCase(st.getSetType())) {
                order = order + NumConstant.INT_ONE;
                settingService.endSettingDetailSave(NumConstant.LONG_LT_TEN, order, stepId);
            }

            // 循环次数大于0，则循环
            if (st.getSettingOrder().equals(loopOrderBegin)) {
                // 补全第一次循环
                for (var sl : settingList) {
                    if (sl.getSettingOrder() > loopOrderBegin && sl.getSettingOrder() <= loopOrderEnd) {

                        order = order + NumConstant.INT_ONE;
                        settingService.settingDetailSave(sl, stepId, order);

                        // 不是搁置指令的后面，增加一个结束指令
                        if (!StepTypeNoEnum.STEP_TYPE_SL_NUM.getCode().equalsIgnoreCase(sl.getSetType())) {
                            order = order + NumConstant.INT_ONE;
                            settingService.endSettingDetailSave(NumConstant.LONG_LT_TEN, order, stepId);
                        }
                    }
                }

                // 只有一次循环
                if (loop == NumConstant.INT_ONE) {

                    order = order + NumConstant.INT_ONE;
                    settingService.settingDetailSave(st, stepId, order);

                    // 不是搁置指令的后面，增加一个结束指令
                    if (!StepTypeNoEnum.STEP_TYPE_SL_NUM.getCode().equalsIgnoreCase(st.getSetType())) {
                        order = order + NumConstant.INT_ONE;
                        settingService.endSettingDetailSave(NumConstant.LONG_LT_TEN, order, stepId);
                    }

                    continue;
                }

                //  中间n-2次循环
                for (int i = NumConstant.INT_ONE; i < loop; i++) {
                    for (var slp : settingList) {
                        if (slp.getSettingOrder() >= loopOrderBegin && slp.getSettingOrder() <= loopOrderEnd) {

                            order = order + NumConstant.INT_ONE;
                            settingService.settingDetailSave(slp, stepId, order);

                            // 不是搁置指令的后面，增加一个结束指令
                            if (!StepTypeNoEnum.STEP_TYPE_SL_NUM.getCode().equalsIgnoreCase(slp.getSetType())) {
                                order = order + NumConstant.INT_ONE;
                                settingService.endSettingDetailSave(NumConstant.LONG_LT_TEN, order, stepId);
                            }

                        }
                    }
                }

                // 循环次数大于2，则补全最后一次循环
                order = order + NumConstant.INT_ONE;
                settingService.settingDetailSave(st, stepId, order);

                // 不是搁置指令的后面，增加一个结束指令
                if (!StepTypeNoEnum.STEP_TYPE_SL_NUM.getCode().equalsIgnoreCase(st.getSetType())) {
                    order = order + NumConstant.INT_ONE;
                    settingService.endSettingDetailSave(NumConstant.LONG_LT_TEN, order, stepId);
                }

            }
        }
    }
}